package com.woniuxy.controlleradvice;

import com.woniuxy.constants.ErrCodeConstants;
import com.woniuxy.exception.BusinessException;
import com.woniuxy.response.ResponseResult;
import com.woniuxy.response.ResponseUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.yaml.snakeyaml.constructor.DuplicateKeyException;

import javax.security.auth.message.AuthException;

@Slf4j
@ControllerAdvice
public class CommonExceptionHandler {

    @ExceptionHandler(AuthException.class)
    @ResponseBody
    public <T> ResponseResult<T> exceptionHandler(AuthException e) {
        // 401未授权
        return ResponseUtil.fail(ErrCodeConstants.AUTH_ERROR, e.getMessage());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public <T> ResponseResult<T> exceptionHandler(MethodArgumentNotValidException e) {
        BindingResult bindingResult = e.getBindingResult();
        String errorMesssage ="invalid.data: ";

        StringBuilder buf = new StringBuilder();
        int i = 0;
        for (FieldError fieldError : bindingResult.getFieldErrors()) {
            if (i > 0) {
                buf.append(";");
            }
            buf.append(fieldError.getDefaultMessage());

            i++;
        }

        errorMesssage += buf.toString();

        return ResponseUtil.fail(ErrCodeConstants.DATA_CHECK, errorMesssage);
    }

    @ExceptionHandler(BusinessException.class)
    @ResponseBody
    public <T> ResponseResult<T> exceptionHandler(BusinessException e) {
        log.warn(e.getErrMsg());
        return ResponseUtil.fail(e.getErrCode(), e.getErrMsg());
    }

    @ExceptionHandler(DuplicateKeyException.class)
    @ResponseBody
    public <T> ResponseResult<T> exceptionHandler(DuplicateKeyException e) {
        log.warn(e.getMessage());
        return ResponseUtil.fail(ErrCodeConstants.BUSINESS_ERROR, "数据库字段重复");
    }

    @ExceptionHandler(BindException.class)
    @ResponseBody
    public <T> ResponseResult<T> bindException(Exception e) {
        log.error("data verify error:", e);
        Throwable cause = this.getThrowableCause(e);
        return ResponseUtil.fail(ErrCodeConstants.DATA_CHECK, cause.getMessage());
    }

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public <T> ResponseResult<T> exceptionHandler(Exception e) {
        log.error("system error:", e);
        Throwable cause = this.getThrowableCause(e);
        return ResponseUtil.fail(ErrCodeConstants.SYSTEM_ERROR, cause.getMessage());
    }



    private Throwable getThrowableCause(Throwable throwable) {
        if (throwable.getCause() != null) {
            return getThrowableCause(throwable.getCause());
        } else {
            return throwable;
        }
    }
}
